package com.rt.code.generator.freemarker.exec;

import com.alibaba.fastjson.JSONObject;
import com.rt.easyjava.base.biz1.bean.TmptData;
import com.rt.easyjava.common.utils.others.SwitchLineCamel;
import com.rt.tmpt.dto.A1TemplateColumnDto;
import com.rt.tmpt.dto.A1TemplateColumnOptionDataDto;
import com.rt.tmpt.dto.A1TemplateColumnOptionDto;
import com.rt.tmpt.dto.A1TemplateTableDto;
import com.rt.tmpt.service.ITemplateService;
import com.rt.tmpt.utils.Config;
import com.rt.tmpt.utils.StringUtils;
import net.sf.json.JSONArray;
import org.springframework.data.domain.Example;

import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.util.*;

/**
 * Created by wxy on 2017/1/28.
 */
public class FmUtils {

    //开发环境工作区目录
    private String projectWeb = Config.projectWeb;
    private String projectBiz = Config.projectBiz;
    private String projectFtl = Config.projectFtl;

    private String datasource;

    public FmUtils(String datasource){
        this.datasource = datasource;
    }


    /**
     *
     * @param templateTable
     * @param dbcolumnsProperty {"table_name_column_name":{"table_name":"","column_name":"","data_type":"int","length":"0"},...}
     * @param columnList
     * @param columnCanAddList
     * @param columnNeedSumList
     * @param conditionColumnMapList
     * @param columnAliasMap 列对应的表的别名，如t1,t2
     * @param columnTableMap 多表时，通过列名找相应表名
     * @param mapTableAliasToName {t1:table1, t2:table2}
     */
    public Map<String, Object> dealColumnList(A1TemplateTableDto templateTable, Map<String,Map<String,String>> dbcolumnsProperty,
                               List<Map<String,Object>> columnList,
                               List<Map<String,Object>> columnCanAddList,
                               List<Map<String,Object>> columnNeedSumList,
                               List<Map<String,Object>>  conditionColumnMapList, Map<String,String> columnAliasMap,
                               Map<String,String> columnTableMap,
                               List<A1TemplateColumnDto> templateTableColumnOptionList,
                               List<Map<String,Object>> columnSqlOptionList,
                               Map<String, String> mapTableAliasToName,
                               Map<String, String> myParamMap){
        Map<String, Object> resultMap = new HashMap<>();
        //Boolean isTreeTable = false;```` ````
        List<A1TemplateColumnDto> a1TemplateColumnDtoList = templateTable.getA1TemplateColumnDtoList();
        String tableName = templateTable.getTableName();

        String module = myParamMap.get("module");
        String classInstance = myParamMap.get("classInstance");

        String columnId4tree = tableName+"_id"; // 内关联外键，说明本身是树表
        for(A1TemplateColumnDto a1TemplateColumnDto : a1TemplateColumnDtoList){
            int deleteFlag = a1TemplateColumnDto.getDeleteFlag();
            if(deleteFlag==1){continue;}
            String columnName = a1TemplateColumnDto.getColumnName();
            String tableAliasName = a1TemplateColumnDto.getTableAliasName();
            tableAliasName = tableAliasName == null ? "" : tableAliasName;
            String columnType = a1TemplateColumnDto.getColumnType();//页面查询字段用的
            String columnNameSql = a1TemplateColumnDto.getColumnNameSql();
            String propertyName = switch2Property(columnName);
            String defaultValue = a1TemplateColumnDto.getDefaultValue();
            String column_tableAliasName = a1TemplateColumnDto.getTableAliasName();
            String dataTransfer = a1TemplateColumnDto.getDataTransfer();
            Integer isHidden = a1TemplateColumnDto.getIsHidden();
            Integer canAdd = a1TemplateColumnDto.getCanAdd();
            dataTransfer = dataTransfer==null?"":dataTransfer;
            // 是否是树表
            /*if (columnName.equalsIgnoreCase(columnId4tree)) {
                isTreeTable = true;``` ```
            }*/

            Map<String,String> columnTypeMap = columnTypeMap(columnTableMap, dbcolumnsProperty, columnName);
            String columnDbType = columnTypeMap.get("columnDbType");
            String columnType4MyBatis = columnTypeMap.get("columnType4MyBatis");
            String columnType4JavaEncap = columnTypeMap.get("columnType4JavaEncap");
            String columnDbTypeLower = columnDbType.toLowerCase();

            //Sum columns
            Integer needSum = a1TemplateColumnDto.getNeedSum();
            String columnNameSqlSum = a1TemplateColumnDto.getColumnNameSqlSum();

            //isquery
            int isQuery = a1TemplateColumnDto.getIsQuery()==null?0:a1TemplateColumnDto.getIsQuery().intValue();
            int dataResource = a1TemplateColumnDto.getDataResource()==null?0:a1TemplateColumnDto.getDataResource().intValue();
            String optionsSql = a1TemplateColumnDto.getOptionsSql();
            String optionsPage = a1TemplateColumnDto.getOptionsPage();
            String queryType = a1TemplateColumnDto.getQueryType(); //eg: between,left like,right like,like,=
            queryType = queryType==null?"":queryType;
            String queryTypeLinkSign = queryType;
            String queryTypePlaceholder = "";
            if(!StringUtils.isNull(queryType)) {
                if (queryType.contains("like")) {
                    queryTypeLinkSign = "like";
                    queryTypePlaceholder = "模糊查询";
                }
            }else {
                queryTypeLinkSign = "=";
            }
            int hasOptions = 0;
            // enum name
            String enumName = firstWord2Upper(propertyName);
            if (dataResource == 1 && !StringUtils.isNull(optionsSql)) { // 枚举列
                enumName = firstWord2Upper(switch2Property(optionsSql));
            }
            //String optionsDefaultKey = "";

            //List<A1TemplateColumnOptionDto> optionDtoListCopy = new ArrayList<A1TemplateColumnOptionDto>();
            /*optionDtoListCopy.addAll(a1TemplateColumnDto.getA1TemplateColumnOptionDtoList());
            if(optionDtoListCopy.size()>0){
                //是多选项，页面显示select
                hasOptions = 1;
                //判断下有没有默认值：有=默认选择默认值，没有=默认选择全部（新加一个全部）
                //加“全部”
                String keyNameDefault = "";
                String valueNameDefault = "全部";
                A1TemplateColumnOptionDto optionDto = new A1TemplateColumnOptionDto();
                optionDto.setKeyName(keyNameDefault);
                optionDto.setValueName(valueNameDefault);
                optionDtoListCopy.add(0, optionDto);
            }*/
            List<Map<String, Object>> optionDtoListCopy = new ArrayList<>();
            Map<String, Object> option;
            for(A1TemplateColumnOptionDto columnOptionDto: a1TemplateColumnDto.getA1TemplateColumnOptionDtoList()){
                option = new HashMap<>();
                option.put("id", Integer.parseInt(columnOptionDto.getKeyName()));
                option.put("name", columnOptionDto.getValueName());
                optionDtoListCopy.add(option);
            }
            if(optionDtoListCopy.size()>0){
                //是多选项，页面显示select
                hasOptions = 1;
            }

            //column alias
            String alias = columnAliasMap.get(columnName);
            String columnNameAlias = columnName;
            if (!StringUtils.isNull(alias)) {
                columnNameAlias = alias + "." + columnName;
            }

            //取表名作为类的前部分
            String tableName2classFirstWordUpper = firstWord2Upper(switch2Property(tableName));
            String columnName2classFirstWordUpper = firstWord2Upper(switch2Property(columnName));
            //生成enum类名
            String enumClassName = tableName2classFirstWordUpper+columnName2classFirstWordUpper;

            //列多选项
            for(A1TemplateColumnDto dtoTmp : templateTableColumnOptionList){
                String columnNameTmp = dtoTmp.getColumnName();
                if(columnNameTmp.equals(columnName)){
                    a1TemplateColumnDto.setA1TemplateColumnOptionJsonArray(dtoTmp.getA1TemplateColumnOptionJsonArray());
                    break;
                }
            }
            // 冻结列
            Boolean fixed = false;
            if (a1TemplateColumnDto.getIsFrozenColumn().intValue() == 1) {
                fixed = true;
            }

            String colTableName = mapTableAliasToName.get(tableAliasName);
            String colClassName = switch2Property(colTableName);
            String colClassNameFirstWordUpper = firstWord2Upper(colClassName);
            String colClassPropertyName = ""; // t2.name, 取name
            if (columnNameSql.contains(".")){
                colClassPropertyName = columnNameSql.substring(columnNameSql.indexOf(".")+1);
                System.out.println("colClassPropertyName1:"+colClassPropertyName);
                colClassPropertyName = switch2Property(colClassPropertyName);//wxy 20200911
                System.out.println("colClassPropertyName2:"+colClassPropertyName);
            }

            // vue select remote url
            String remoteUrl = "";

            if (dataResource == 0) {
                remoteUrl = "";
            }else if (dataResource == 1) {
                remoteUrl = "/"+module+"/enum/getData4AddBy";
            }else {
                remoteUrl = "/"+module+"/coding/"+classInstance+"/select4column";
            }

            Map<String,Object > columnMap = new HashMap<String, Object>();
            columnMap.put("columnName",columnName);
            columnMap.put("columnNameSql", columnNameSql);
            columnMap.put("comment", a1TemplateColumnDto.getComment());
            // 多表：列所属表的，别名-表名-对应类名
            columnMap.put("tableAliasName",tableAliasName);
            columnMap.put("colTableName",colTableName);
            columnMap.put("colClassInstance",colClassName);
            columnMap.put("colClassNameFirstWordUpper",colClassNameFirstWordUpper);
            columnMap.put("colClassPropertyName",colClassPropertyName);
            //
            columnMap.put("propertyName",propertyName);
            columnMap.put("propertyNameFirstWordUpper",firstWord2Upper(propertyName));
            columnMap.put("columnShowName",a1TemplateColumnDto.getColumnShowName());
            columnMap.put("columnType",columnType);
            columnMap.put("columnTip",a1TemplateColumnDto.getColumnTip());
            columnMap.put("columnWidth",a1TemplateColumnDto.getColumnWidth());
            columnMap.put("needSum", "" + needSum);
            columnMap.put("needSumBool", needSum==0?false:true);
            columnMap.put("canAdd", canAdd);
            columnMap.put("columnNameFirstWordUpper",firstWord2Upper(columnName));
            columnMap.put("columnDbType",columnDbType);
            columnMap.put("columnType4JavaEncap",columnType4JavaEncap);
            columnMap.put("columnDbTypeLower",columnDbTypeLower);//Action,Model中属性类型
            columnMap.put("columnType4MyBatis", columnType4MyBatis);
            columnMap.put("isPrimaryKey", columnName.equalsIgnoreCase(templateTable.getPrimaryKey()) ? "true" : "false");
            columnMap.put("columnNameSqlSum",columnNameSqlSum);
            columnMap.put("dataResource", dataResource);
            columnMap.put("remoteUrl", remoteUrl);
            columnMap.put("enumName", enumName);
            columnMap.put("optionsSql", optionsSql);
            columnMap.put("optionsPage", optionsPage);
            columnMap.put("columnNameAlias", columnNameAlias);
            columnMap.put("column_tableAliasName", column_tableAliasName);
            columnMap.put("columnTableAliasName", column_tableAliasName);
            columnMap.put("isHidden", isHidden);
            columnMap.put("isQuery", isQuery);
            columnMap.put("queryType", queryType);
            columnMap.put("queryTypeLinkSign", queryTypeLinkSign);
            columnMap.put("queryTypePlaceholder", queryTypePlaceholder);
            columnMap.put("enumClassName", enumClassName);
            columnMap.put("enumClassNamefirstWord2Lower", firstWord2Lower(enumClassName));
            columnMap.put("enumClassNamefirstWord2Upper", firstWord2Upper(enumClassName));
            columnMap.put("a1TemplateColumnOptionJsonArray", a1TemplateColumnDto.getA1TemplateColumnOptionJsonArray());
            columnMap.put("a1TemplateColumnOptionDtoList", optionDtoListCopy);
            columnMap.put("defaultValue",defaultValue);
            columnMap.put("dataTransfer",dataTransfer);
            columnMap.put("fixed",fixed);
            columnMap.put("fixedStr",fixed.toString());
            //UI
            columnMap.put("hasOptions", hasOptions);
            columnMap.put("defaultKey", defaultValue);
            columnList.add(columnMap);

            //can add/edit column
            if(canAdd!=null && canAdd.intValue() ==1){
                columnCanAddList.add(columnMap);
            }
            //sum
            if(needSum!=null && needSum.intValue()>=1){
                columnNeedSumList.add(columnMap);
            }
            //query condition
            if(isQuery == 1) {
                conditionColumnMapList.add(columnMap);
            }
            // ds = 2 , sql取值
            if(dataResource == 2){
                columnSqlOptionList.add(columnMap);
            }
        }
        //resultMap.put("isTreeTable", isTreeTable);
        return resultMap;
    }

    public static Map<String, Object> parseConfigJson(String cfgJsonStr, String tableName) {
        Map<String, Object> map = new HashMap<>();
        com.alibaba.fastjson.JSONObject cfgJson = null;
        // tree
        Boolean isTreeTable = false;
        Boolean hasAsideTree = false;
        // One to Many
        List<Map<String, Object>> o2mList = new ArrayList<>();
        if (!StringUtils.isNull(cfgJsonStr)) {
            cfgJson = com.alibaba.fastjson.JSONObject.parseObject(cfgJsonStr);
            // Tree
            com.alibaba.fastjson.JSONObject treeJson = cfgJson.getObject("tree", com.alibaba.fastjson.JSONObject.class);
            if (treeJson != null) {
                isTreeTable = treeJson.getBoolean("enable");
            }
            // One to many
            /*JSONObject otmJson = cfgJson.getObject("otm", JSONObject.class);
            if (otmJson != null) {
                hasO2M = otmJson.getBoolean("enable");
                tableNameO2M = otmJson.getString("tableName");
                classNameO2M = FmUtils.switch2Property(tableNameO2M);
                tableNameFirstWordUpperO2M = FmUtils.firstWord2Upper(tableNameO2M);
                tableNameFirstWordLowerO2M = FmUtils.firstWord2Lower(tableNameO2M);
                classNameFirstWordUpperO2M = FmUtils.firstWord2Upper(classNameO2M);
                classNameFirstWordLowerO2M = FmUtils.firstWord2Lower(classNameO2M);
            }*/

            com.alibaba.fastjson.JSONArray otmJsonArr = new com.alibaba.fastjson.JSONArray();
            Object o = cfgJson.getObject("otm", Object.class);
            if (o instanceof JSONObject) {
                JSONObject otmJson = cfgJson.getObject("otm", JSONObject.class);
                otmJsonArr.add(otmJson);
            }
            else{
                otmJsonArr = cfgJson.getJSONArray("otm");
            }
            if (otmJsonArr != null) {
                for (int i=0; i<otmJsonArr.size(); i++) {
                    com.alibaba.fastjson.JSONObject jo = otmJsonArr.getJSONObject(i);
                    Boolean hasO2M = jo.getBoolean("enable");
                    String tableNameO2M = jo.getString("slaveTableName");
                    if (StringUtils.isNull(tableNameO2M)) { // 兼容老版本
                        tableNameO2M = jo.getString("tableName");
                    }
                    String classNameO2M = FmUtils.switch2Property(tableNameO2M);
                    String tableNameFirstWordUpperO2M = FmUtils.firstWord2Upper(tableNameO2M);
                    String tableNameFirstWordLowerO2M = FmUtils.firstWord2Lower(tableNameO2M);
                    String classNameFirstWordUpperO2M = FmUtils.firstWord2Upper(classNameO2M);
                    String classNameFirstWordLowerO2M = FmUtils.firstWord2Lower(classNameO2M);
                    //
                    String column = jo.getString("column");
                    String slaveColumn = jo.getString("slaveColumn");
                    if (StringUtils.isNull(column)) {
                        column = "id";
                    }if (StringUtils.isNull(slaveColumn)) {
                        slaveColumn = tableName+"_id";
                    }
                    Map<String, Object> o2mMap = new HashMap<>();
                    o2mMap.put("hasO2M",hasO2M);
                    o2mMap.put("column",column);
                    o2mMap.put("property",FmUtils.switch2Property(column));
                    o2mMap.put("slaveColumn",slaveColumn);
                    o2mMap.put("slaveProperty",FmUtils.switch2Property(slaveColumn));

                    o2mMap.put("tableNameO2M",tableNameO2M);
                    o2mMap.put("classNameO2M",classNameO2M);
                    o2mMap.put("tableNameFirstWordUpperO2M",tableNameFirstWordUpperO2M);
                    o2mMap.put("tableNameFirstWordLowerO2M",tableNameFirstWordLowerO2M);
                    o2mMap.put("classNameFirstWordUpperO2M",classNameFirstWordUpperO2M);
                    o2mMap.put("classNameFirstWordLowerO2M",classNameFirstWordLowerO2M);
                    o2mList.add(o2mMap);
                }
            }
            //hasAsideTree
            com.alibaba.fastjson.JSONObject asideTreeJson = cfgJson.getObject("asideTree", JSONObject.class);
            if (asideTreeJson != null) {
                hasAsideTree = asideTreeJson.getBoolean("enable");
            }
        }

        map.put("cfgJson",cfgJson);
        map.put("isTreeTable",isTreeTable);
        map.put("hasAsideTree",hasAsideTree);
        map.put("o2mList",o2mList);
        /*map.put("hasO2M",hasO2M);
        map.put("tableNameO2M",tableNameO2M);
        map.put("tableNameFirstWordUpperO2M",tableNameFirstWordUpperO2M);
        map.put("tableNameFirstWordLowerO2M",tableNameFirstWordLowerO2M);
        map.put("classNameFirstWordUpperO2M",classNameFirstWordUpperO2M);
        map.put("classNameFirstWordLowerO2M",classNameFirstWordLowerO2M);*/

        return map;
    }

    // a2company_a2company_name, 有问题？？？？
    private Map<String,String> columnTypeMap(Map<String,String> columnTableMap,Map<String,Map<String,String>> dbcolumnsProperty,String columnName){
        Map<String,String> map = new HashMap<String, String>();

        String dbColumnsPropertyKey = columnTableMap.get(columnName)+"_"+columnName;
        //多表关联时，这个列可能是其它表的，而dbcolumnsProperty是主表的，默认给varchar做数据展示
        String columnDbTypeTemp = "";
        if(!dbcolumnsProperty.keySet().contains(dbColumnsPropertyKey)){
            columnDbTypeTemp = "varchar";
        }else {
            columnDbTypeTemp = dbcolumnsProperty.get(dbColumnsPropertyKey).get("data_type");//数据库里的
        }
        String columnDbType = columnDbTypeTemp;
        String columnType4MyBatis = "";
        String columnType4JavaEncap = "";
        if(columnDbTypeTemp.equalsIgnoreCase("datetime") ||
                columnDbTypeTemp.contains("date")||
                columnDbTypeTemp.contains("timestamp")){
            columnDbType = "Date";
            columnType4JavaEncap = "Date";
            columnType4MyBatis = "Date";
        }else if(columnDbTypeTemp.equalsIgnoreCase("bigint")){
            columnDbType = "long";
            columnType4JavaEncap = "Long";
            columnType4MyBatis = "BIGINT";
        }else if(columnDbTypeTemp.equalsIgnoreCase("int")
                || columnDbTypeTemp.equalsIgnoreCase("integer")){
            columnDbType = "int";
            columnType4JavaEncap = "Integer";
            columnType4MyBatis = "INTEGER";
        }else if(columnDbTypeTemp.equalsIgnoreCase("double")
                || columnDbTypeTemp.equalsIgnoreCase("numeric")){
            columnDbType = "double";
            columnType4JavaEncap = "BigDecimal";
            columnType4MyBatis = "BigDecimal";
        }else if(columnDbTypeTemp.equalsIgnoreCase("varchar")
                || columnDbTypeTemp.equalsIgnoreCase("longtext")){
            columnDbType = "String";
            columnType4JavaEncap = "String";
            columnType4MyBatis = "VARCHAR";
        }else{
            columnDbType = "String";
            columnType4JavaEncap = "String";
            columnType4MyBatis = "VARCHAR";
        }

        map.put("columnDbType",columnDbType);
        map.put("columnType4MyBatis",columnType4MyBatis);
        map.put("columnType4JavaEncap",columnType4JavaEncap);
        return map;
    }


    /**
     * 整理合计字段 eg:sum(balance) ;
     * columnNameSqlSum 不存在时，使用拼接方法sum+(column)；
     * columnNameSqlSum 存在时，使用columnNameSqlSum字段 ，分以下两种情况处理:
     * needSum = 1时，使用拼接方法sum+(column);
     * needSum = 2时，columnNameSqlSum中可能是文字（eg:合计），直接使用
     * @param columnNeedSumList
     * @param sb4columnSumStr
     * @Param sumTitleList :eg:[{columnName:balancedate,title:合计},...]
        //eg:balancedate,合计
        Map<String,String> map = new HashMap<String, String>();
        map.put("columnName",columnName);
        map.put("title",columnNameSqlSum);
        sumTitleList.add(map);
     */
    public boolean dealNeedSumColumn(List<Map<String,Object>> columnNeedSumList, StringBuffer sb4columnSumStr,Map<String,String> sumTitleMap){
        boolean needSumBoolean = false;

        for(Map<String,Object > columnMap : columnNeedSumList) {
            String columnNameSqlSum = (String)columnMap.get("columnNameSqlSum");
            int needSum = Integer.parseInt((String) columnMap.get("needSum"));
            String columnName = (String)columnMap.get("columnName");
            String columnTableAliasName = (String)columnMap.get("columnTableAliasName");


            if (!StringUtils.isNull(columnNameSqlSum)) {// 默认补sum()
                if (!columnNameSqlSum.contains("(")) {
                    columnNameSqlSum = "sum("+columnNameSqlSum+")";
                }
                if (needSum == 2) {
                    //eg:balancedate,合计
                    sumTitleMap.put(columnName,columnNameSqlSum);
                    /*Map<String,String> map = new HashMap<String, String>();
                    map.put("columnName",columnName);
                    map.put("columnNameFirstWord2Upper",firstWord2Upper(columnName));
                    map.put("title",columnNameSqlSum);
                    sumTitleList.add(map);*/

                    sb4columnSumStr.append("'").append(columnNameSqlSum).append("'").append(" as ").append(columnName).append(",");
                } else {
                    sb4columnSumStr.append(columnNameSqlSum).append(" as ").append(columnName).append(",");
                }
            } else {
                String columnNameSumTmp = columnName;
                if(!StringUtils.isNull(columnTableAliasName)){
                    columnNameSumTmp = columnTableAliasName+"."+columnName;
                }/*else if(!StringUtils.isNull(tableAliasName)){
                    columnNameSumTmp = tableAliasName+"."+columnName;
                }*/
                sb4columnSumStr.append("sum(").append(columnNameSumTmp).append(") as ").append(columnName).append(",");
            }
        }

        if(sb4columnSumStr.length()>1){
            sb4columnSumStr.deleteCharAt(sb4columnSumStr.length()-1);
        }

        return needSumBoolean;
    }


    /**
     * 整理可编辑列成字符串，mapper.xml中insert和update相关列使用字符串
     * @param columnCanAddList
     * @param sbCanAddColumn
     * @param sbCanAddColumnValue
     * @param sbCanEditColumn
     */
    public void dealCanEditColumn(List<Map<String,Object>> columnCanAddList, StringBuffer sbCanAddColumn,
                                  StringBuffer sbCanAddColumnValue,StringBuffer sbCanEditColumn){
        for(Map<String,Object > columnCanAddMap : columnCanAddList){
            String columnName = (String)columnCanAddMap.get("columnName");
            String propertyName = switch2Property(columnName);
            String columnType4MyBatis = (String)columnCanAddMap.get("columnType4MyBatis");
            sbCanAddColumn.append(columnName).append(",");
            sbCanAddColumnValue.append("#{").append(propertyName).append(",jdbcType=").append(columnType4MyBatis).append("},");
            sbCanEditColumn.append(columnName).append("=").append("#{").append(propertyName).append(",jdbcType=").append(columnType4MyBatis).append("},");
        }
        if(sbCanAddColumn.length()>1){
            sbCanAddColumn.deleteCharAt(sbCanAddColumn.length()-1);
            sbCanAddColumnValue.deleteCharAt(sbCanAddColumnValue.length()-1);
            sbCanEditColumn.deleteCharAt(sbCanEditColumn.length()-1);
        }
    }

    /**
     * 查询字段列 eg:select c1,c2,c3  mapper.xml中使用
     * @param columnList
     * @param sb4columnStr
     */
    public void dealColumnstr4Select(A1TemplateTableDto table, List<Map<String,Object>> columnList, StringBuffer sb4columnStr){
        for(Map<String,Object > columnMap : columnList){
            String columnName = (String)columnMap.get("columnName");
            //String columnType = columnMap.get("columnType");
            String columnDbType = ((String)columnMap.get("columnDbType")).toLowerCase();

            //生成columnNameSql
            String columnNameSql = (String)columnMap.get("columnNameSql");
            String tableAliasName = table.getTableAliasName();
            String columnTableAliasName = (String)columnMap.get("column_tableAliasName");
            //有可能本身有值，直接使用
            if(StringUtils.isNull(columnNameSql)){
                if(!StringUtils.isNull(columnTableAliasName)){
                    columnNameSql = columnTableAliasName+"."+columnName;
                }else if(!StringUtils.isNull(tableAliasName)){
                    columnNameSql = tableAliasName+"."+columnName;
                }
            }

            if(!StringUtils.isNull(columnDbType) && (columnDbType.equals("timestamp")||columnDbType.equals("datetime") )){
                //单表时，可能为空。select name from table1
                //多表时，可能不为空。select t1.name from table1 t1 ...
                if(StringUtils.isNull(columnNameSql)){//单表
                    sb4columnStr.append(columnName).append(",");
                }else {//多表
                    sb4columnStr.append(columnNameSql).append(" as ").append(columnName)/*.append("_Str")*/.append(",");
                }
            }else {
                //单表时，可能为空。select name from table1
                //多表时，可能不为空。select t1.name from table1 t1 ...
                if(StringUtils.isNull(columnNameSql)){//单表
                    sb4columnStr.append(columnName).append(",");
                }else {//多表
                    sb4columnStr.append(columnNameSql).append(" as ").append(columnName).append(",");
                }
            }
        }
        sb4columnStr.deleteCharAt(sb4columnStr.length()-1);
    }


    public String dealHiddenFiledsJson(A1TemplateTableDto templateTable){
        JSONArray jsonArray = new JSONArray();
        /*for(A1TemplateColumnDto column: templateTable.getA1TemplateColumnDtoList()){
            int dataResource = column.getDataResource()==null?0:column.getDataResource().intValue();
            if(A1TemplateColumnDto.dataResource_OptionsTable == dataResource
                    || A1TemplateColumnDto.dataResource_OptionsTableKeyEqualValue == dataResource ){
                if(column.getA1TemplateColumnOptionDtoList().size()>0){
                    String columnName = column.getColumnName();
                    A1TemplateColumnDto a1TemplateColumnDto = new A1TemplateColumnDto();
                    a1TemplateColumnDto.setColumnName(columnName);

                    for(A1TemplateColumnOptionDto option: column.getA1TemplateColumnOptionDtoList()){
                        long optionId = option.getId();
                        String keyName = option.getKeyName();
                        String valueName=option.getValueName();
                        A1TemplateColumnOptionDto a1TemplateColumnOptionDto = new A1TemplateColumnOptionDto();
                        a1TemplateColumnOptionDto.setId(optionId);
                        a1TemplateColumnOptionDto.setKeyName(keyName);
                        a1TemplateColumnOptionDto.setValueName(valueName);
                        a1TemplateColumnDto.getA1TemplateColumnOptionDtoList().add(a1TemplateColumnOptionDto);
                        JSONArray jsonArrayHidCol = new JSONArray();
                        for(A1TemplateColumnOptionHidColDto hiddenColumn:option.getA1TemplateColumnOptionHidColDtoList()){
                            String columName = hiddenColumn.getColumName();
                            JSONObject jsonObjectHidCol = new JSONObject();
                            jsonObjectHidCol.put("text", columName);
                            jsonArrayHidCol.add(jsonObjectHidCol);
                        }
                        JSONObject jsonObjectOption = new JSONObject();
                        jsonObjectOption.put("optionId",""+optionId);
                        jsonObjectOption.put("filedList",jsonArrayHidCol);
                        jsonArray.add(jsonObjectOption);
                    }
                }
            }
        }*/
        return jsonArray.toString();
    }

    /**
     * when data resource = 1 and 4, then option is from column itself
     * @param tableDto
     * @return
     */
    public List<Map> queryOption4ColumnSelfList(A1TemplateTableDto tableDto){
        List<Map> list = new ArrayList<Map>();

        String tableName = tableDto.getTableName();
        //取表名作为类的前部分
        String tableName2classFirstWordUpper = firstWord2Upper(switch2Property(tableName));
        //所有列
        List<A1TemplateColumnDto> columnDtoList = tableDto.getA1TemplateColumnDtoList();
        for(A1TemplateColumnDto columnDto : columnDtoList){
            int dataSource = columnDto.getDataResource()==null?0:columnDto.getDataResource().intValue();
            //只取dataResource_OptionsTable = 1
            //dataResource_OptionsTableKeyEqualValue = 4
            if(dataSource!=1 && dataSource!=4){continue;}
            //没option数据不处理
            if(columnDto.getA1TemplateColumnOptionDtoList().size()==0){continue;}
            String columnName = columnDto.getColumnName();
            String propertyName = switch2Property(columnName);
            String columnName2classFirstWordUpper = firstWord2Upper(propertyName);
            //生成enum类名
            String className = tableName2classFirstWordUpper+columnName2classFirstWordUpper;
            List<A1TemplateColumnOptionDto> columnOptionDtoList = columnDto.getA1TemplateColumnOptionDtoList();
            List<A1TemplateColumnOptionDataDto> columnOptionDataDtoList = new ArrayList<A1TemplateColumnOptionDataDto>();
            for(A1TemplateColumnOptionDto optionDto:columnOptionDtoList){
                A1TemplateColumnOptionDataDto optionDataDto = new A1TemplateColumnOptionDataDto();
                optionDataDto.setOptionId(optionDto.getId());
                optionDataDto.setOptionName(optionDto.getOptionName()==null?"":optionDto.getOptionName());
                optionDataDto.setKeyName(optionDto.getKeyName());
                optionDataDto.setValueName(optionDto.getValueName());
                columnOptionDataDtoList.add(optionDataDto);
            }
            Map map = new HashMap();
            map.put("className",className);
            map.put("propertyName",propertyName);
            map.put("propertyNameFirstWord2Upper",columnName2classFirstWordUpper);
            map.put("columnOptionDataDtoList", columnOptionDataDtoList);
            list.add(map);
        }

        return list;
    }

    /**
     * 生成ftl文件
     * @param list
     */
    public void genOptionEnumFile4ColumnSelf(List<Map> list)throws Exception{
        for (Map map : list) {
            Map map1 = new HashMap();
            map1.put("className",map.get("className"));
            map1.put("columnOptionDataDtoList",map.get("columnOptionDataDtoList"));
        }
    }

    /**
     * 数据字典生成出来
     * @param templateService
     * @return map是一列的options
     */
    /*public List<Map> queryOptionDataListBySearch(ITemplateService templateService, Long id){
        List<String> columnNameList = new ArrayList<String>();
        {
            List<A1TemplateColumnOptionDataDto> columnOptionDataDto = templateService.queryOptionDataListBySearch(Example.of(new A1TemplateColumnOptionData()));
            for (A1TemplateColumnOptionDataDto optionDataDto : columnOptionDataDto) {
                String columnName = optionDataDto.getColumnName();
                if (!columnNameList.contains(columnName)) {
                    columnNameList.add(columnName);
                }
            }
        }
        List<Map> list = new ArrayList<>();
        for (String columnName : columnNameList) {
            A1TemplateColumnOptionData a1TemplateColumnOptionDataParam = new A1TemplateColumnOptionData();
            a1TemplateColumnOptionDataParam.setColumnName(columnName);
            Example example = Example.of(a1TemplateColumnOptionDataParam);
            List<A1TemplateColumnOptionDataDto> columnOptionDataDtoList = templateService.queryOptionDataListBySearch(example);
            for(A1TemplateColumnOptionDataDto optionDataDto : columnOptionDataDtoList){
                optionDataDto.setOptionId(0L);
            }
            String className = firstWord2Upper(switch2Property(columnName));
            Map map = new HashMap();
            map.put("className",className);
            map.put("classNameFirstWordLower",firstWord2Lower(className));
            map.put("columnOptionDataDtoList", columnOptionDataDtoList);
            list.add(map);
        }
        return list;
    }*/

    /**
     * 数据字典生成出来
     * @param templateService
     * @return map是一列的options
     */
    public Map queryTmptDataById(ITemplateService templateService, Long id){
        TmptData tmptData = templateService.queryTmptDataById(id);
        String columnName = tmptData.getColumnName();
        String className = firstWord2Upper(switch2Property(columnName));

        Map map = new HashMap();
        map.put("tmptData",tmptData);
        map.put("className",className);
        map.put("classNameFirstWordLower",firstWord2Lower(className));
        map.put("columnOptionDataDtoList", tmptData.getTmptDataOptionList());

        return map;
    }




    /**
     * 生成ftl文件
     * @param list
     */
    public void genOptionDataEnumFile(List<Map> list)throws Exception{
        for (Map map : list) {
            Map map1 = new HashMap();
            map1.put("className",map.get("className"));
            map1.put("columnOptionDataDtoList",map.get("columnOptionDataDtoList"));
        }
    }


    /**
     * 按模板生成各种文件
     * @param map
     * @param type=1：生成web层；type=2：生成service层; type=3:生成所有
     */
    public void genFile(Map map, int type)throws Exception{
        String classNameFirstWordUpper = (String)map.get("classNameFirstWordUpper");
        String classNameFirstWordLower = (String)map.get("classNameFirstWordLower");

    }




    //==================================================
    //                  工具类
    //==================================================
    public static String firstWord2Upper(String str){
        String firstWord = str.substring(0,1).toUpperCase();
        String str1 = firstWord + str.substring(1);
        return str1;
    }

    public static String firstWord2Lower(String str){
        String firstWord = str.substring(0,1).toLowerCase();
        String str1 = firstWord + str.substring(1);
        return str1;
    }

    // Bean --> Map 1: 利用Introspector和PropertyDescriptor 将Bean --> Map
    public static Map<String, Object> transBean2Map(Object obj) {

        if(obj == null){
            return null;
        }
        Map<String, Object> map = new HashMap<String, Object>();
        try {
            BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass());
            PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
            for (PropertyDescriptor property : propertyDescriptors) {
                String key = property.getName();

                // 过滤class属性
                if (!key.equals("class")) {
                    // 得到property对应的getter方法
                    Method getter = property.getReadMethod();
                    Object value = getter.invoke(obj);

                    map.put(key, value);
                }

            }
        } catch (Exception e) {
            System.out.println("transBean2Map Error " + e);
        }

        return map;

    }



    /**
     * 字段转成属性
     * @param columnName
     * @return
     */
    public static String switch2Property(String columnName){
        return SwitchLineCamel.switch2Property(columnName);
    }


    /**
     * 属性转字段
     * @param property
     * @return
     */
    public static String switch2Column(String property){
        return SwitchLineCamel.switch2Column(property);
    }


    /**
     * parse tableNameSql, for tableNameList and tableAliasList
     * String tableNameSql = "a2user t1 left join a2dept t2 on t1.dept_id=t2.id left join a2company t3 on t2.company_id=t3.id";
     * [a2user,a2dept,a2company] [t1,t2,t3]
     * @param tableNameSql
     * @param tableNameList
     * @param tableAliasList
     */
    public static void parseTableNameSql (String tableNameSql, List<String> tableNameList, List<String> tableAliasList) {
        // String tableNameSql = "a2user t1 left join a2dept t2 on t1.dept_id=t2.id left join a2company t3 on t2.company_id=t3.id";
        tableNameSql = tableNameSql.trim();
        List<String> list = Arrays.asList(tableNameSql.split(" "));
        // 'join' 位置底标
        List<Integer> listIndex_Join = new ArrayList<>();
        listIndex_Join.add(-1);
        for (int i=0; i<list.size(); i++) {
            String s = list.get(i);
            if(s.equalsIgnoreCase("join")){
                listIndex_Join.add(i);
            }
        }
        // 取join后的表名和别名
        for (Integer index: listIndex_Join) {
            String tableName = list.get(index + 1);
            String tableAlias = list.get(index + 2);
            tableNameList.add(tableName);
            tableAliasList.add(tableAlias);
        }

    }

    /**
     * MAP:
     * t1: table1
     * t2: table2
     * @param tableAliasList
     * @param tableNameList
     */
    public static Map<String, String> mapTableAliasToName(List<String> tableAliasList, List<String> tableNameList) {
        Map<String, String> map = new HashMap<>();
        for (int i=0; i<tableAliasList.size(); i++) {
            map.put(tableAliasList.get(i), tableNameList.get(i));
        }
        return map;
    }

    public static void main(String[] args) {
        System.out.println(firstWord2Upper(switch2Property("options_sql")));
    }


}
